#include "timer.h"       // 包含定时器类的声明
#include "utils.h"       // 包含工具函数（如GetElapsedMS获取系统毫秒数）

namespace fiber 
{

// 实现Timer类的比较器：用于std::set对Timer::ptr的排序
bool Timer::Comparator::operator()(const Timer::ptr &lhs, const Timer::ptr &rhs) const {
    // 处理空指针情况（确保排序稳定性）
    if (!lhs && !rhs) {
        return false;  // 两个空指针视为相等，不交换
    }
    if (!lhs) {
        return true;   // 左空指针排在右非空指针前面
    }
    if (!rhs) {
        return false;  // 右空指针排在左非空指针后面
    }
    // 核心排序逻辑：按下次执行时间（next_）升序排列（最近要执行的在前）
    if (lhs->m_next < rhs->m_next) {
        return true;
    }
    if (rhs->m_next < lhs->m_next) {
        return false;
    }
    // 若next_相等，按对象地址排序（避免set认为两个不同对象相等而无法插入）
    return lhs.get() < rhs.get();
}

Timer::Timer(uint64_t ms, std::function<void()> cb, bool recuring, TimerManager *manager)
: m_recurring(recuring), m_ms(ms), m_cb(cb), m_manager(manager) {
    m_next = GetElapsedMS() + m_ms;  // GetElapsedMS()获取系统启动到现在的毫秒数
}

Timer::Timer(uint64_t next) 
: m_next(next) {}

bool Timer::cancel() {
    RWMutex::WriteLock lock(m_manager->m_rwmutex);  // 加写锁（修改集合需要写权限）
    if (m_cb) {  // 若回调存在（未被取消）
        m_cb = nullptr;  // 清除回调（标记为无效）
        auto it = m_manager->m_timers.find(shared_from_this());  // 查找自身在集合中的位置
        m_manager->m_timers.erase(it);  // 从集合中移除
        return true;
    }
    return false;  // 已取消过，返回失败
}

bool Timer::refresh() {
    RWMutex::WriteLock lock(m_manager->m_rwmutex);  // 加写锁
    if (!m_cb) {  // 回调已无效（已取消），无法刷新
        return false;
    }
    auto it = m_manager->m_timers.find(shared_from_this());  // 查找自身
    if (it == m_manager->m_timers.end()) {  // 不在集合中，返回失败
        return false;
    }
    m_manager->m_timers.erase(it);  // 移除旧的
    m_next = GetElapsedMS() + m_ms;  // 重新计算下次执行时间（当前时间+周期）
    m_manager->m_timers.insert(shared_from_this());  // 重新插入集合
    return true;
}

bool Timer::reset(uint64_t ms, bool from_now) {
    if (ms == m_ms && !from_now) {  // 周期不变且不从现在开始，无需调整
        return true;
    }
    RWMutex::WriteLock lock(m_manager->m_rwmutex);
    if (!m_cb) {  // 回调无效，返回失败
        return false;
    }
    auto it = m_manager->m_timers.find(shared_from_this());
    if (it == m_manager->m_timers.end()) {  // 不在集合中，返回失败
        return false;
    }
    m_manager->m_timers.erase(it);  // 移除旧的
    uint64_t start = 0;
    if (from_now) {
        start = GetElapsedMS();  // 从当前时间开始
    } 
    else {
        start = m_next - m_ms;  // 从原周期的起始时间开始（保持周期连贯性）
    }
    m_ms = ms;  // 更新周期
    m_next = start + m_ms;  // 计算新的下次执行时间
    m_manager->addTimer(shared_from_this(), lock);  // 重新加入管理器
    return true;
}

TimerManager::TimerManager() { m_previouseTime = GetElapsedMS(); }

TimerManager::~TimerManager() {}

Timer::ptr TimerManager::addTimer(uint64_t ms, std::function<void()> cb, bool recurring) {
    Timer::ptr timer(new Timer(ms, cb, recurring, this));  // 创建定时器对象
    RWMutex::WriteLock lock(m_rwmutex);  // 加写锁
    addTimer(timer, lock);  // 调用内部方法添加到集合
    return timer;
}

static void OnTimer(std::weak_ptr<void> weak_cond, std::function<void()> cb) {
    std::shared_ptr<void> tmp = weak_cond.lock();  // 尝试获取强引用（检查对象是否存活）
    if (tmp) {  // 对象存活，执行回调
        cb();
    }
}

Timer::ptr TimerManager::addConditionTimer(uint64_t ms, std::function<void()> cb, std::weak_ptr<void> weak_cond,
                                           bool recurring) {
    // 绑定OnTimer为实际回调，传入弱指针和用户回调
    return addTimer(ms, std::bind(&OnTimer, weak_cond, cb), recurring);
}

uint64_t TimerManager::getNextTimer() {
    RWMutex::ReadLock lock(m_rwmutex);  // 读锁（仅查询，不修改）
    m_tickled = false;  // 重置"触发过首部插入"标记

    if (m_timers.empty()) {
        return ~0ull;  // 无定时器，返回最大uint64_t（表示无限等待）
    }

    const Timer::ptr& next = *m_timers.begin();  // 集合首元素是最近要执行的定时器
    uint64_t now_ms = GetElapsedMS();  // 当前时间
    
    if (now_ms >= next->m_next) {  // 已到期
        return 0;
    } 
    else {  // 未到期，返回剩余时间
        return next->m_next - now_ms;
    }
}

void TimerManager::listExpiredCb(std::vector<std::function<void()>> &cbs) {
    uint64_t now_ms = GetElapsedMS();  // 当前时间
    std::vector<Timer::ptr> expired;  // 存储已过期的定时器

    {
        RWMutex::ReadLock lock(m_rwmutex);  // 先加读锁检查是否为空（优化：避免不必要的写锁）
        if (m_timers.empty()) {
            return;
        }
    }

    RWMutex::WriteLock lock(m_rwmutex);  // 加写锁（需要修改集合）
    if (m_timers.empty()) {
        return;
    }

    bool rollover = false;  // 是否发生时钟回滚（系统时间被调小）
    if (detectClockRolllover(now_ms)) {  // 检测时钟回滚
        rollover = true;
    }
    // 若未回滚且最近的定时器未到期，直接返回
    if (!rollover && ((*m_timers.begin())->m_next > now_ms)) {
        return;
    }

    // 创建一个临时定时器（next_ = 当前时间），用于查找所有过期的定时器
    Timer::ptr now_timer(new Timer(now_ms));
    // 查找第一个未过期的定时器（若回滚，视为所有定时器都可能过期，直接取end()）
    auto it = rollover ? m_timers.end() : m_timers.lower_bound(now_timer);  // 第一个大于等于的
    // 处理next_等于当前时间的情况（避免漏检）
    while (it != m_timers.end() && (*it)->m_next == now_ms) {
        ++it;
    }
    // 将所有过期的定时器（begin()到it）存入expired向量
    expired.insert(expired.begin(), m_timers.begin(), it);
    // 从集合中移除过期的定时器
    m_timers.erase(m_timers.begin(), it);

    // 收集过期定时器的回调函数
    cbs.reserve(expired.size());  // 预分配空间（优化性能）
    for (auto& timer : expired) {
        cbs.push_back(timer->m_cb);
        if (timer->m_recurring) {  // 若是循环定时器，重新计算next_并插入集合
            timer->m_next = now_ms + timer->m_ms;  // 下次执行时间 = 当前时间 + 周期
            m_timers.insert(timer);
        } 
        else {  // 非循环定时器，清除回调（标记为无效）
            timer->m_cb = nullptr;
        }
    }
}

bool TimerManager::hasTimer() {
    RWMutex::ReadLock lock(m_rwmutex);  // 读锁
    return !m_timers.empty();
}

void TimerManager::addTimer(Timer::ptr val, RWMutex::WriteLock &lock) {
    // 插入定时器到集合，返回迭代器
    // insetr返回值是一个pair类型first是一个迭代器，second是一个布尔值
    auto it = m_timers.insert(val).first;
    // 判断是否插入到了集合首部，且未触发过首部插入事件
    bool at_front = (it == m_timers.begin()) && !m_tickled;
    if (at_front) {
        m_tickled = true;  // 标记已触发，避免重复
    }
    lock.unlock();  // 提前解锁（减少锁持有时间）
    if (at_front) {
        OnTimerInsertedAtFront();  // 触发"首部插入"事件（子类实现，如唤醒等待线程）
    }
}

bool TimerManager::detectClockRolllover(uint64_t now_ms) {
    bool rollover = false;
    if (now_ms < m_previouseTime && now_ms < (m_previouseTime - 60 * 60 * 1000)) {  // 差值>1小时
        rollover = true;
    }
    m_previouseTime = now_ms;  // 更新上次时间
    return rollover;
}

}  // namespace fiber